Skip to content

Conversation

@rekmarks
Copy link
Member

@rekmarks rekmarks commented Jan 14, 2026

Summary

  • Add modular controller architecture with POLA attenuation via makeFacet()
  • Add ControllerStorage abstraction with Immer-based state management and debounced persistence
  • Add Controller abstract base class
  • Add CapletController for managing installed caplets
  • Add storage adapters (ChromeStorage)

Part 2 of 4 in PR stack
Depends on: #751
Followed by: #753


Note

Establishes a modular controller architecture with validated caplet lifecycle management and durable state.

  • Controllers: Adds abstract Controller, POLA helper makeFacet, and ControllerStorage (Immer-based, debounced persistence) with a Chrome storage adapter
  • Caplet management: New CapletController (install/uninstall/list/get/getByService) with manifest validation and subcluster launch/terminate integration; extensive unit tests
  • App wiring: initializeControllers creates controllers with kernel-backed launch/terminate; background initializes controllers and exposes omnium.caplet and kernel/ping on globals; manifest.json gains storage permission
  • Extension: Background now wraps ping and default subcluster startup in try/catch, forwarding errors via offscreenStream.throw
  • Tooling/infra: Adds deps (@endo/exo, @metamask/superstruct, immer, semver, etc.), type defs, e2e utilities/tests, and updates coverage thresholds

Written by Cursor Bugbot for commit 9583876. This will update automatically on new commits. Configure here.

@rekmarks rekmarks requested a review from a team as a code owner January 14, 2026 22:27
@socket-security
Copy link

socket-security bot commented Jan 14, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​types/​semver@​7.7.0 ⏵ 7.7.1100 +110075 +181100
Addedimmer@​10.2.0991008393100

View full report

@rekmarks rekmarks marked this pull request as draft January 14, 2026 23:26
@rekmarks rekmarks force-pushed the rekm/controller-architecture branch 2 times, most recently from 6736065 to 89e5113 Compare January 15, 2026 00:00
@rekmarks rekmarks force-pushed the rekm/controller-architecture branch from 89e5113 to ee93a06 Compare January 15, 2026 06:31
github-merge-queue bot pushed a commit that referenced this pull request Jan 20, 2026
Answers @kumavis's challenge of "What're you afraid of CapTP or
something?" by replacing our kernel JSON-RPC API with `E()` on a facet
of the kernel. This makes it easy to expose as much of the kernel API as
we want via eventual send, and allows us to benefit from pipelining
internally. In addition, it facilitates the removal of the command
stream and the related RPC API logic. Finally, a number of
rationalizations are applied to the extension and omnium.

This PR is part of a stack followed by: #752, #753, and #754



<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> Introduces CapTP-based communication and removes the JSON-RPC command
stream.
> 
> - Add CapTP utilities in `kernel-browser-runtime`:
`makeBackgroundCapTP`, `makeKernelCapTP`, `makeKernelFacade`, and
JSON-RPC `captp` notification helpers; export new `KernelFacade` and
`CapTPMessage` types
> - Update `kernel-worker` to use CapTP for background↔kernel messaging;
initialize kernel without a command stream; route internal RPC only for
panel/internal comms
> - Refactor `@MetaMask/ocap-kernel` to drop command stream handling and
kernel RPC entrypoints; `Kernel.make` now accepts only platform services
and the database; adjust `stop()` accordingly
> - Migrate extension and omnium backgrounds/offscreens to CapTP over
`ChromeRuntimeDuplexStream`, use global `E` and `kernel`/`omnium`
helpers; remove `env/dev-console` and background trusted prelude files;
add TS globals
> - Add unit and integration tests for CapTP (`background-captp`,
kernel-side CapTP, and E() end-to-end); introduce
`vitest.integration.config.ts` and `test:integration` scripts; CI gains
an "Integration Tests" job
> - Update deps (add `@endo/captp`, `@endo/eventual-send`), tsconfigs,
build constants, and minor coverage thresholds
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
cbf22fd. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Base automatically changed from rekm/captp-infrastructure to main January 20, 2026 19:31
rekmarks and others added 8 commits January 20, 2026 12:47
Implement Phase 1.2 of the omnium plan - Define Caplet Structure:

- Add modular controller architecture with POLA attenuation via makeFacet()
- Add storage abstraction layer (StorageAdapter, NamespacedStorage)
- Add Chrome storage adapter for platform storage
- Add CapletController for managing installed caplets
- Add Caplet types with superstruct validation
- Wire CapletController into background.ts and expose on globalThis.omnium.caplet
- Add comprehensive unit tests for all controller code
- Update PLAN.md to reflect implementation
Consolidate CapletControllerState from multiple top-level keys
(installed, manifests, subclusters, installedAt) into a single
`caplets: Record<CapletId, InstalledCaplet>` structure.

Changes:
- Add ControllerStorage abstraction using Immer for state management
- Controllers work with typed state object instead of storage keys
- Only modified top-level keys are persisted (via Immer patches)
- Remove state corruption checks (no longer possible with atomic storage)
- Fix makeFacet type - use string | symbol instead of keyof MethodGuard
- Update PLAN.md to reflect new storage architecture

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add abstract Controller class with state management via ControllerStorage
- Convert CapletController to extend Controller base class
- Use makeFacet() pattern for returning hardened exo methods
- Add base-controller tests (12 tests)
- Add semver deep import type declaration
- Add storage permission to manifest.json

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Convert ControllerStorage from factory to class with static make() method
- Implement synchronous update() with debounced fire-and-forget persistence
- Fix critical debounce bug: accumulate modified keys across debounce window
- Implement bounded latency (timer not reset, max delay = one debounce interval)
- Add immediate writes when idle > debounceMs for better responsiveness
- Add clear() and clearState() methods to reset storage to defaults
- Remove old namespaced-storage implementation
- Refactor all tests to use actual ControllerStorage with mock adapters
- Add shared makeMockStorageAdapter() utility in test/utils.ts
- Update controllers to create their own storage from adapters

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Remove strict reverse DNS format requirement for CapletId to allow more flexibility during early development. Now accepts any non-empty ASCII string without whitespace, removing restrictions on hyphens, underscores, uppercase, and segment count.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@rekmarks rekmarks force-pushed the rekm/controller-architecture branch from d014ffd to 1ab49c9 Compare January 20, 2026 22:09
@rekmarks rekmarks marked this pull request as ready for review January 21, 2026 17:42
@rekmarks rekmarks marked this pull request as draft January 21, 2026 17:47
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants